package TypeInterpreter;
import org.apache.commons.lang3.StringUtils;

public class Interpreter {
	static int current_id = 0;
	
	public static abstract class Type {
		int id;
		abstract Type apply(int i, Type t);
		Type(){
			id = current_id;
			current_id++;
		}
		Type error(){
			System.out.println("Error");
			return null;
		}
		
		
	}
	
	public static class QualFuncType extends Type {
		
		Type[] function_parts;
		
		private QualFuncType(Type[] f_part){
			function_parts = f_part;
		}
		
		Type applyArgs(Type[] args){
			for (int i = 0; i < args.length; i++){
				if (!function_parts[i].equals(args[i])){
					return super.error();
				}
			}
			return function_parts[function_parts.length - 1];
		}
		
		Type apply(int i, Type t) {
			if (function_parts[i].equals(t)){
				Type[] f_part = new Type[function_parts.length - 1];
				int t_curr = 0;
				for (Type lp_t: function_parts)
					if (t_curr != i){
						f_part[t_curr] = lp_t;
						t_curr += 1;
					}
				if (f_part.length == 1)
					return f_part[0];
				else 
					return new QualFuncType(f_part);
			}
			else 
				return super.error();
		}
		
		public String toString(){
			String[] str_parts = new String[function_parts.length];
			for (int i = 0; i < str_parts.length; i++)
				str_parts[i] = function_parts[i].toString();
			return StringUtils.join(str_parts);
		}
	}
	
	
	public static class QualType extends Type {
		int type_id;
		String type_name;
		Type apply(int i, Type t) {
			return null;
		} 
		
		public String toString(){
			return type_name;
		}
		
		boolean equals(Type t){
			return type_name.equals(t.toString());
		}
	}
	
	
	public static class UnQualFunc extends Type {

		Type apply(int i, Type t) {
			return null;
		}		
	}
	
	public static class UnQualType extends Type {
		Type apply(int i, Type t) {
			return null;
		}
	}
}
